package LibDL.supporting;

import LibDL.core.Tensor;
import LibDL.core.functional;
import LibDL.core.functional_utils;

public class CheckMemory {
    public CheckMemory() {
        check();
    }

    static public int called_times = 0;

    static public int check_times = 0;

    static public double init_ratio = 0.5;

    static public double adjusted_cpu_ratio = init_ratio;

    static public double adjusted_cuda_ratio = init_ratio;

    static public double max_ratio = 0.95;

    static public double update_limit = 0.01;

    public static void check() {
//        For debug:
//            System.out.println("CUDA : " + functional_utils.cuda_memory_allocated_ratio());
//            System.out.println("CPU  : " + functional_utils.cpu_memory_allocated_ratio());
        check_times++;
        double cpu_ratio_now = functional_utils.cpu_memory_allocated_ratio();
        double cuda_ratio_now = functional_utils.cuda_memory_allocated_ratio();
        if (functional.is_cuda_available() && cuda_ratio_now > adjusted_cuda_ratio
                || cpu_ratio_now > adjusted_cpu_ratio) {
            System.gc();
            called_times++;
            double cpu_ratio_nxt = functional_utils.cpu_memory_allocated_ratio();
            double cuda_ratio_nxt = functional_utils.cuda_memory_allocated_ratio();

            if (Math.abs(cpu_ratio_now - cpu_ratio_nxt) < update_limit
                    && cpu_ratio_nxt > adjusted_cpu_ratio) {
                adjusted_cpu_ratio = Math.min(cpu_ratio_now, max_ratio);
            } else if (adjusted_cpu_ratio > init_ratio && adjusted_cpu_ratio > cpu_ratio_nxt) {
                adjusted_cpu_ratio = Math.max(cpu_ratio_nxt, init_ratio);
            }

            if (Math.abs(cuda_ratio_now - cuda_ratio_nxt) < update_limit
                    && cuda_ratio_nxt > adjusted_cuda_ratio) {
                adjusted_cuda_ratio = Math.min(cuda_ratio_now, max_ratio);
            } else if (adjusted_cuda_ratio > init_ratio && adjusted_cuda_ratio > cuda_ratio_nxt) {
                adjusted_cuda_ratio = Math.max(cuda_ratio_nxt, init_ratio);
            }

//            For debug
//            System.out.println("Call gc " + called_times + " times!");
        }
    }

    static public void debug_countdown(int n) {

        try {
            for (int i = n; i > 0; i--) {
                System.out.println(i);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Start");
    }
}
